"""
微信告警推送系统主窗口
"""
import os
import sys
import time
import threading
import tkinter as tk
from tkinter import ttk, messagebox, scrolledtext
from datetime import datetime
from typing import Optional, Dict, Any, List

from src.utils.logger import logger
from src.utils.config import config_manager
from src.wechat.login import wechat_login
from src.wechat.message import wechat_message
from src.database.mysql import mysql_manager
from src.scheduler.tasks import task_scheduler


class MainWindow:
    """主窗口类，用于显示微信告警推送系统主界面"""
    
    def __init__(self):
        """初始化主窗口"""
        self.root = tk.Tk()
        self.root.title("微信告警推送系统")
        self.root.geometry("1000x800")  # 增加窗口默认大小
        self.root.minsize(1000, 800)    # 增加窗口最小大小
        
        # 窗口关闭标志
        self.is_closing = False
        
        # 状态变量
        self.wechat_status_var = tk.StringVar(value="未检测")
        self.monitor_status_var = tk.StringVar(value="未启动")
        self.db_status_var = tk.StringVar(value="未连接")
        self.last_check_var = tk.StringVar(value="无")
        self.check_minutes_var = tk.StringVar(value=config_manager.get_value("scheduler", "check_minutes", "0,15,30,45"))
        self.resend_daily_alarms_var = tk.BooleanVar(value=config_manager.get_value("scheduler", "resend_daily_alarms", False))
        
        # 日志级别变量
        self.log_levels = ["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]
        self.log_level_var = tk.StringVar(value=config_manager.get_value("system", "log_level", "INFO"))
        
        # 创建界面
        self._create_ui()
        
        # 绑定关闭事件
        self.root.protocol("WM_DELETE_WINDOW", self._on_closing)
        
        # 启动微信状态检查
        wechat_login.start_status_check(self._on_wechat_login)
        
        # 启动数据库状态检查
        self._check_db_status()
        
        # 更新状态
        self._update_status()
        
    def _create_ui(self):
        """创建界面"""
        # 创建主框架
        main_frame = ttk.Frame(self.root, padding="10")
        main_frame.pack(fill=tk.BOTH, expand=True)
        
        # 创建状态框架
        status_frame = ttk.LabelFrame(main_frame, text="系统状态", padding="10")
        status_frame.pack(fill=tk.X, pady=5)
        
        # 状态网格 - 所有状态放在一行
        status_grid = ttk.Frame(status_frame)
        status_grid.pack(fill=tk.X)
        
        # 微信状态
        ttk.Label(status_grid, text="微信状态:").grid(row=0, column=0, sticky=tk.W, padx=5, pady=5)
        self.wechat_status_label = ttk.Label(status_grid, textvariable=self.wechat_status_var)
        self.wechat_status_label.grid(row=0, column=1, sticky=tk.W, padx=5, pady=5)
        
        # 添加微信检测状态按钮
        self.check_wechat_btn = ttk.Button(status_grid, text="检测状态", command=self._check_wechat_status)
        self.check_wechat_btn.grid(row=0, column=2, sticky=tk.W, padx=5, pady=5)
        
        # 监控状态
        ttk.Label(status_grid, text="监控状态:").grid(row=0, column=3, sticky=tk.W, padx=5, pady=5)
        self.monitor_status_label = ttk.Label(status_grid, textvariable=self.monitor_status_var)
        self.monitor_status_label.grid(row=0, column=4, sticky=tk.W, padx=5, pady=5)
        
        # 数据库状态
        ttk.Label(status_grid, text="数据库状态:").grid(row=0, column=5, sticky=tk.W, padx=5, pady=5)
        self.db_status_label = ttk.Label(status_grid, textvariable=self.db_status_var)
        self.db_status_label.grid(row=0, column=6, sticky=tk.W, padx=5, pady=5)
        
        # 最后检查时间
        ttk.Label(status_grid, text="最后检测:").grid(row=0, column=7, sticky=tk.W, padx=5, pady=5)
        self.last_check_label = ttk.Label(status_grid, textvariable=self.last_check_var)
        self.last_check_label.grid(row=0, column=8, sticky=tk.W, padx=5, pady=5)
        
        # 创建控制框架
        control_frame = ttk.LabelFrame(main_frame, text="监控控制", padding="10")
        control_frame.pack(fill=tk.X, pady=5)
        
        # 控制按钮
        btn_frame = ttk.Frame(control_frame)
        btn_frame.pack(fill=tk.X, pady=5)
        
        # 启动监控按钮
        self.start_btn = ttk.Button(btn_frame, text="启动监控", command=self._start_monitor)
        self.start_btn.pack(side=tk.LEFT, padx=5)
        
        # 停止监控按钮
        self.stop_btn = ttk.Button(btn_frame, text="停止监控", command=self._stop_monitor)
        self.stop_btn.pack(side=tk.LEFT, padx=5)
        self.stop_btn.config(state=tk.DISABLED)
        
        # 立即检测按钮
        self.check_now_btn = ttk.Button(btn_frame, text="立即检测", command=self._check_now)
        self.check_now_btn.pack(side=tk.LEFT, padx=5)
        
        # 显示微信按钮
        # self.show_wechat_btn = ttk.Button(btn_frame, text="显示微信", command=self._show_wechat)
        # self.show_wechat_btn.pack(side=tk.LEFT, padx=5)
        
        # 创建配置框架
        config_frame = ttk.LabelFrame(main_frame, text="系统设置", padding="10")
        config_frame.pack(fill=tk.X, pady=5)
        
        # 检查分钟设置
        minutes_frame = ttk.Frame(config_frame)
        minutes_frame.pack(fill=tk.X, pady=5)
        
        ttk.Label(minutes_frame, text="检查分钟:").pack(side=tk.LEFT, padx=5)
        minutes_entry = ttk.Entry(minutes_frame, textvariable=self.check_minutes_var, width=30)
        minutes_entry.pack(side=tk.LEFT, padx=5)
        
        ttk.Label(minutes_frame, text="(格式: 0,15,30,45)").pack(side=tk.LEFT, padx=5)
        
        save_btn = ttk.Button(minutes_frame, text="保存设置", command=self._save_schedule)
        save_btn.pack(side=tk.LEFT, padx=5)
        
        # 重复发送设置 - 移到保存设置按钮后面（暂时不需要）
        # resend_check = ttk.Checkbutton(minutes_frame, text="重复发送当日告警", variable=self.resend_daily_alarms_var, command=self._update_resend_setting)
        # resend_check.pack(side=tk.LEFT, padx=5)
        
        # 日志级别设置
        log_level_frame = ttk.Frame(config_frame)
        log_level_frame.pack(fill=tk.X, pady=5)
        
        ttk.Label(log_level_frame, text="日志级别:").pack(side=tk.LEFT, padx=5)
        
        # 日志级别下拉框
        log_level_combobox = ttk.Combobox(log_level_frame, textvariable=self.log_level_var, values=self.log_levels, width=10, state="readonly")
        log_level_combobox.pack(side=tk.LEFT, padx=5)
        
        # 保存日志级别按钮
        save_log_level_btn = ttk.Button(log_level_frame, text="保存日志级别", command=self._save_log_level)
        save_log_level_btn.pack(side=tk.LEFT, padx=5)
        
        # 创建自定义消息框架
        custom_msg_frame = ttk.LabelFrame(main_frame, text="自定义消息", padding="10")
        custom_msg_frame.pack(fill=tk.X, pady=5)
        
        # 自定义消息内容
        msg_content_frame = ttk.Frame(custom_msg_frame)
        msg_content_frame.pack(fill=tk.X, pady=5)
        
        # 接收人输入框
        receiver_frame = ttk.Frame(msg_content_frame)
        receiver_frame.pack(fill=tk.X, pady=5)
        
        ttk.Label(receiver_frame, text="接收人:").pack(side=tk.LEFT, padx=5)
        self.receiver_entry = ttk.Entry(receiver_frame, width=30)
        self.receiver_entry.pack(side=tk.LEFT, padx=5)
        self.receiver_entry.insert(0, "文件传输助手")
        
        ttk.Label(msg_content_frame, text="消息内容:").pack(anchor=tk.W, padx=5)
        
        # 自定义消息文本框
        self.custom_msg_text = tk.Text(msg_content_frame, height=3, width=50)
        self.custom_msg_text.pack(fill=tk.X, padx=5, pady=5)
        
        # 添加提示语
        self.custom_msg_text.insert(tk.END, "请输入要发送的消息内容...")
        self.custom_msg_text.config(fg="gray")
        
        # 绑定事件，当获取焦点时清除提示语
        self.custom_msg_text.bind("<FocusIn>", self._on_message_focus_in)
        # 绑定事件，当失去焦点且为空时显示提示语
        self.custom_msg_text.bind("<FocusOut>", self._on_message_focus_out)
        
        # 发送按钮
        send_frame = ttk.Frame(custom_msg_frame)
        send_frame.pack(fill=tk.X, pady=5)
        
        # 发送按钮
        send_btn = ttk.Button(send_frame, text="发送消息", command=self._send_custom_message)
        send_btn.pack(side=tk.LEFT, padx=5)
        
        # 创建日志框架 - 增加高度
        log_frame = ttk.LabelFrame(main_frame, text="运行日志", padding="10")
        log_frame.pack(fill=tk.BOTH, expand=True, pady=5)
        
        # 日志文本框 - 增加高度
        self.log_text = scrolledtext.ScrolledText(log_frame, height=40)
        self.log_text.pack(fill=tk.BOTH, expand=True)
        self.log_text.config(state=tk.DISABLED)
        
        # 启动日志监控
        self._start_log_monitor()
    
    def _update_status(self):
        """更新状态显示"""
        if self.is_closing:
            return
        
        # 更新微信状态
        if wechat_login.is_logged_in:
            self.wechat_status_var.set("已登录")
            self.wechat_status_label.configure(foreground="green")
        else:
            self.wechat_status_var.set("未登录")
            self.wechat_status_label.configure(foreground="red")
        
        # 更新监控状态
        if task_scheduler.is_running:
            self.monitor_status_var.set("运行中")
            self.monitor_status_label.configure(foreground="green")
            self.start_btn.config(state=tk.DISABLED)
            self.stop_btn.config(state=tk.NORMAL)
        else:
            self.monitor_status_var.set("已停止")
            self.monitor_status_label.configure(foreground="red")
            self.start_btn.config(state=tk.NORMAL)
            self.stop_btn.config(state=tk.DISABLED)
        
        # 更新数据库状态
        if self.db_status_var.get() == "已连接":
            self.db_status_label.configure(foreground="green")
        else:
            self.db_status_label.configure(foreground="red")
        
        # 更新最后检查时间颜色
        if self.last_check_var.get() != "无":
            self.last_check_label.configure(foreground="blue")
        else:
            self.last_check_label.configure(foreground="gray")
        
        # 安排下一次更新
        self.root.after(1000, self._update_status)
    
    def _check_db_status(self):
        """检查数据库状态"""
        if self.is_closing:
            return
        
        # 在后台线程中检查数据库连接
        def check_db():
            if mysql_manager.connect():
                self.db_status_var.set("已连接")
            else:
                self.db_status_var.set("连接失败")
        
        # 启动线程
        threading.Thread(target=check_db, daemon=True).start()
        
        # 安排下一次检查
        self.root.after(30000, self._check_db_status)  # 每30秒检查一次
    
    def _on_wechat_login(self):
        """微信登录成功回调"""
        self.wechat_status_var.set("已登录")
    
    def _start_monitor(self):
        """启动监控"""
        # 检查微信是否已登录
        if not wechat_login.is_logged_in:
            messagebox.showwarning("警告", "微信未登录，请先登录微信")
            self._show_wechat()
            return
        
        # 启动调度器
        if task_scheduler.start():
            self.update_monitor_status(True)
            logger.info("监控已启动")
        else:
            messagebox.showerror("错误", "启动监控失败")
            logger.error("启动监控失败")
    
    def update_monitor_status(self, is_running: bool):
        """更新监控状态
        
        Args:
            is_running: 是否正在运行
        """
        if is_running:
            self.monitor_status_var.set("运行中")
            self.start_btn.config(state=tk.DISABLED)
            self.stop_btn.config(state=tk.NORMAL)
        else:
            self.monitor_status_var.set("已停止")
            self.start_btn.config(state=tk.NORMAL)
            self.stop_btn.config(state=tk.DISABLED)
    
    def _stop_monitor(self):
        """停止监控"""
        # 停止调度器
        if task_scheduler.stop():
            self.update_monitor_status(False)
            logger.info("监控已停止")
        else:
            messagebox.showerror("错误", "停止监控失败")
            logger.error("停止监控失败")
    
    def _check_now(self):
        """立即检测"""
        # 检查微信是否已登录
        if not wechat_login.is_logged_in:
            messagebox.showwarning("警告", "微信未登录，请先登录微信")
            self._show_wechat()
            return
        
        # 禁用按钮，避免重复点击
        self.check_now_btn.config(state=tk.DISABLED)
        
        # 在后台线程中执行检查
        def do_check():
            try:
                logger.info("开始手动检测告警...")
                result = task_scheduler.run_task_now()
                
                # 更新最后检查时间
                now = datetime.now().strftime("%H:%M:%S")
                self.last_check_var.set(now)
                
                # 在UI线程中显示结果弹窗
                if result["success"]:
                    # 构建详细信息
                    detail = f"检测结果:\n"
                    detail += f"- 今日告警总数: {result.get('total_alarms', 0)}条\n"
                    detail += f"- {'新' if not task_scheduler.resend_daily_alarms else ''}告警数量: {result.get('new_alarms', 0)}条\n"
                    
                    if result.get('new_alarms', 0) > 0:
                        detail += f"- 发送成功: {result.get('sent_groups', 0)}/{result.get('total_groups', 0)}组\n"
                        detail += f"- 联系人成功率: {result.get('contact_success', 0)}/{result.get('total_contacts', 0)}\n"
                        detail += f"- 耗时: {result.get('elapsed_time', 0):.2f}秒"
                        
                        # 在UI线程中显示成功消息
                        self.root.after(0, lambda: messagebox.showinfo("检测完成", detail))
                    else:
                        # 在UI线程中显示信息消息
                        self.root.after(0, lambda: messagebox.showinfo("检测完成", detail))
                else:
                    # 在UI线程中显示错误消息
                    self.root.after(0, lambda: messagebox.showerror("检测失败", result.get("message", "未知错误")))
                
                logger.info(f"手动检测完成，时间: {now}")
            except Exception as e:
                logger.error(f"手动检测异常: {e}")
                # 在UI线程中显示异常消息
                self.root.after(0, lambda: messagebox.showerror("检测异常", f"发生异常: {e}"))
            finally:
                # 恢复按钮状态
                self.root.after(0, lambda: self.check_now_btn.config(state=tk.NORMAL))
        
        # 启动线程
        threading.Thread(target=do_check, daemon=True).start()
    
    def _show_wechat(self):
        """显示微信窗口"""
        # 显示微信窗口
        if wechat_login.show_wechat():
            logger.info("已显示微信窗口")
        else:
            logger.error("显示微信窗口失败")
            messagebox.showerror("错误", "显示微信窗口失败，请手动打开微信")
    
    def _save_schedule(self):
        """保存调度设置"""
        # 获取分钟设置
        minutes = self.check_minutes_var.get()
        
        # 验证格式
        try:
            # 分割并转换为整数
            minute_list = []
            for part in minutes.split(","):
                if part.strip():
                    m = int(part.strip())
                    if 0 <= m < 60:
                        minute_list.append(m)
            
            # 至少有一个有效值
            if not minute_list:
                raise ValueError("没有有效的分钟值")
            
            # 更新设置
            if task_scheduler.update_schedule(minutes):
                logger.info(f"调度设置已更新: {minutes}")
                messagebox.showinfo("成功", "调度设置已更新")
            else:
                messagebox.showerror("错误", "更新调度设置失败")
                logger.error("更新调度设置失败")
        except Exception as e:
            messagebox.showerror("错误", f"分钟格式无效: {e}")
            logger.error(f"分钟格式无效: {e}")
    
    def _save_log_level(self):
        """保存日志级别设置"""
        # 获取日志级别
        log_level = self.log_level_var.get()
        
        # 验证日志级别
        if log_level not in self.log_levels:
            messagebox.showerror("错误", "无效的日志级别")
            logger.error(f"无效的日志级别: {log_level}")
            return
        
        # 更新配置
        config_manager.set_value("system", "log_level", log_level)
        if config_manager.save():
            logger.info(f"日志级别已更新: {log_level}")
            messagebox.showinfo("成功", "日志级别已更新")
            
            # 重新配置日志级别
            logger.setLevel(log_level)
        else:
            messagebox.showerror("错误", "更新日志级别失败")
            logger.error("更新日志级别失败")
    
    def _update_resend_setting(self):
        """更新重复发送设置"""
        resend = self.resend_daily_alarms_var.get()
        if task_scheduler.update_resend_setting(resend):
            logger.info(f"重复发送设置已更新: {resend}")
        else:
            messagebox.showerror("错误", "更新重复发送设置失败")
            logger.error("更新重复发送设置失败")
            # 恢复原值
            self.resend_daily_alarms_var.set(config_manager.get_value("scheduler", "resend_daily_alarms", False))
    
    def _send_custom_message(self):
        """发送自定义消息"""
        # 检查微信是否已登录
        if not wechat_login.is_logged_in:
            messagebox.showwarning("警告", "微信未登录，请先登录微信")
            self._show_wechat()
            return
        
        # 获取接收人
        receiver = self.receiver_entry.get().strip()
        if not receiver:
            messagebox.showerror("错误", "接收人不能为空")
            logger.warning("发送自定义消息失败: 接收人为空")
            return
            
        # 获取消息内容
        message = self.custom_msg_text.get("1.0", tk.END).strip()
        
        # 检查是否是提示文本
        if message == "请输入要发送的消息内容...":
            messagebox.showerror("错误", "请输入消息内容")
            logger.warning("发送自定义消息失败: 未输入消息内容")
            return
        
        if not message:
            messagebox.showerror("错误", "消息内容不能为空")
            logger.warning("发送自定义消息失败: 消息内容为空")
            return
        
        # 在后台线程中发送消息
        def send_message():
            logger.info(f"开始发送自定义消息到: {receiver}...")
            if wechat_message.send_text(receiver, message):
                logger.info(f"自定义消息发送成功到: {receiver}")
                # 在UI线程中显示成功消息
                self.root.after(0, lambda: messagebox.showinfo("成功", f"消息已成功发送到: {receiver}"))
            else:
                logger.error(f"自定义消息发送失败到: {receiver}")
                # 在UI线程中显示错误消息
                self.root.after(0, lambda: messagebox.showerror("错误", "发送消息失败，请查看日志"))
        
        # 启动线程
        threading.Thread(target=send_message, daemon=True).start()
        
        # 清空消息内容
        self.custom_msg_text.delete("1.0", tk.END)

    def _check_wechat_status(self):
        """立即检查微信登录状态"""
        # 禁用按钮，避免重复点击
        self.check_wechat_btn.config(state=tk.DISABLED)
        
        # 在后台线程中执行检查
        def do_check():
            try:
                logger.info("开始检查微信登录状态...")
                
                # 检查微信是否在运行
                if wechat_login.check_wechat_running():
                    # 检查登录状态
                    if wechat_login.check_login():
                        logger.info("微信已登录")
                        self.wechat_status_var.set("已登录")
                        self.wechat_status_label.configure(foreground="green")
                    else:
                        logger.info("微信未登录")
                        self.wechat_status_var.set("未登录")
                        self.wechat_status_label.configure(foreground="red")
                        
                        # 如果未登录，尝试显示微信窗口
                        self._show_wechat()
                else:
                    logger.info("微信未运行")
                    self.wechat_status_var.set("未运行")
                    self.wechat_status_label.configure(foreground="red")
                    
                    # 尝试启动微信
                    if wechat_login.start_wechat():
                        logger.info("已启动微信")
                    else:
                        logger.error("启动微信失败")
                        messagebox.showerror("错误", "启动微信失败，请手动打开微信")
            finally:
                # 恢复按钮状态
                self.root.after(0, lambda: self.check_wechat_btn.config(state=tk.NORMAL))
        
        # 启动线程
        threading.Thread(target=do_check, daemon=True).start()

    def _on_message_focus_in(self, event):
        """消息输入框获取焦点事件"""
        # 如果是提示文本，则清空并恢复正常颜色
        if self.custom_msg_text.get("1.0", tk.END).strip() in ["", "请输入要发送的消息内容..."]:
            self.custom_msg_text.delete("1.0", tk.END)
            self.custom_msg_text.config(fg="black")
    
    def _on_message_focus_out(self, event):
        """消息输入框失去焦点事件"""
        # 如果为空，显示提示文本
        if not self.custom_msg_text.get("1.0", tk.END).strip():
            self.custom_msg_text.delete("1.0", tk.END)
            self.custom_msg_text.insert(tk.END, "请输入要发送的消息内容...")
            self.custom_msg_text.config(fg="gray")

    def _start_log_monitor(self):
        """启动日志监控"""
        # 日志文件路径
        # 获取应用程序路径，支持打包后的可执行文件
        if getattr(sys, 'frozen', False):
            # 如果是打包后的可执行文件
            app_dir = os.path.dirname(sys.executable)
            log_file = os.path.join(app_dir, "logs", "wechat_alarm.log")
        else:
            # 如果是开发环境
            log_file = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))), "logs", "wechat_alarm.log")
        
        # 如果日志文件不存在，创建空文件
        if not os.path.exists(log_file):
            os.makedirs(os.path.dirname(log_file), exist_ok=True)
            with open(log_file, "w", encoding="utf-8") as f:
                pass
        else:
            # 如果日志文件存在，记录启动分隔线
            with open(log_file, "a", encoding="utf-8") as f:
                f.write(f"\n{'-' * 50}\n")
                f.write(f"系统启动时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
                f.write(f"{'-' * 50}\n\n")
        
        # 获取文件大小，只从文件末尾开始监控
        try:
            last_position = os.path.getsize(log_file)
        except:
            last_position = 0
        
        # 记录日志文件路径，方便调试
        logger.info(f"日志文件路径: {log_file}")
        
        # 监控线程
        def monitor_log():
            nonlocal last_position
            
            while not self.is_closing:
                try:
                    # 读取日志文件
                    if os.path.exists(log_file):
                        with open(log_file, "r", encoding="utf-8", errors="ignore") as f:
                            # 移动到上次读取位置
                            f.seek(last_position)
                            
                            # 读取新内容
                            new_content = f.read()
                            
                            # 更新位置
                            last_position = f.tell()
                        
                        # 如果有新内容，添加到日志文本框
                        if new_content:
                            # 在UI线程中更新日志文本框
                            def update_log():
                                self.log_text.config(state=tk.NORMAL)
                                for line in new_content.splitlines():
                                    self.log_text.insert(tk.END, f"{line}\n")
                                self.log_text.see(tk.END)
                                self.log_text.config(state=tk.DISABLED)
                            
                            # 如果在主线程中，直接更新
                            if threading.current_thread() is threading.main_thread():
                                update_log()
                            else:
                                # 否则，使用after方法在主线程中更新
                                self.root.after(0, update_log)
                except Exception as e:
                    print(f"读取日志异常: {e}")
                    logger.error(f"读取日志异常: {e}")
                
                # 休眠一段时间
                time.sleep(1)
        
        # 启动监控线程
        threading.Thread(target=monitor_log, daemon=True).start()

    
    def _on_closing(self):
        """窗口关闭事件"""
        # 设置关闭标志
        self.is_closing = True
        
        # 停止微信状态检查
        wechat_login.stop_status_check()
        
        # 停止调度器
        task_scheduler.stop()
        
        # 关闭数据库连接
        mysql_manager.close()
        
        # 销毁窗口
        self.root.destroy()
        
        # 退出程序
        sys.exit(0)
    
    def run(self):
        """运行主窗口"""
        # 初始日志
        logger.info("微信告警推送系统已启动")
        
        # 运行主循环
        self.root.mainloop()


# 单例实例
_instance = None


def get_instance() -> MainWindow:
    """获取主窗口实例"""
    global _instance
    if _instance is None:
        _instance = MainWindow()
    return _instance 